package com.lxx.codegen.mbgplugins;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.mybatis.generator.api.GeneratedJavaFile;
import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.PluginAdapter;
import org.mybatis.generator.config.Context;
import org.mybatis.generator.internal.util.JavaBeansUtil;
import org.springframework.jdbc.core.metadata.GenericTableMetaDataProvider;

import com.lxx.codegen.Property;
import com.lxx.codegen.TemplateProcessor;

import freemarker.core.ParseException;
import freemarker.template.Configuration;
import freemarker.template.MalformedTemplateNameException;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import freemarker.template.TemplateExceptionHandler;
import freemarker.template.TemplateNotFoundException;

/**
 * 业务代码自动生成插件
 * 目前支持：service层， controller层
 * @author zhuawa
 *
 */
public class BusinessPlugin extends PluginAdapter {
	
	private String prjPath;
	private String javaModelPackage;
	private String javaClientPackage; // mapper的路径
	
	/** 列表展示的列的偏移,  一般前两列是 复选框 和 序号 */
	final int colIndexOffset = 2; 

	@Override
	public boolean validate(List<String> warnings) {
		// TODO Auto-generated method stub
		return true;
	}
	
	@Override
	public void setContext(Context context) {
		this.prjPath = context.getProperty("prjPath");
		this.javaModelPackage = context.getJavaModelGeneratorConfiguration().getTargetPackage();
		this.javaClientPackage = context.getJavaClientGeneratorConfiguration().getTargetPackage();
		super.setContext(context);
	}

	@Override
	public List<GeneratedJavaFile> contextGenerateAdditionalJavaFiles(IntrospectedTable introspectedTable) {
		try {
			Configuration cfg = new Configuration(Configuration.VERSION_2_3_22);
			cfg.setDirectoryForTemplateLoading(
					new File(this.getClass().getResource("/templates").getPath()));
			cfg.setDefaultEncoding("UTF-8");

			cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);

			// 表对应的类名
			String modelName = JavaBeansUtil
					.getCamelCaseString(introspectedTable.getFullyQualifiedTable().getIntrospectedTableName(), true);
			// 表的备注,注释
			String modelRemark = introspectedTable.getRemarks();
			modelRemark = StringUtils.stripEnd(modelRemark, "表");
			// 收集所有字段
			// List<Property> properties = new ArrayList<Property>();
			String pk = JavaBeansUtil
					.getCamelCaseString(introspectedTable.getPrimaryKeyColumns().get(0).getActualColumnName(), false);
			String pkType = introspectedTable.getPrimaryKeyColumns().get(0).getFullyQualifiedJavaType().getShortName();
			String pkParse = "";
			String pkTypeImport = "";
			if ("Long".equals(pkType)) {
				pkParse = "Long.parseLong(" + pk + ")";
			} else if ("Integer".equals(pkType)) {
				pkParse = "Integer.parseInt(" + pk + ")";
			} else if ("String".equals(pkType)) {
				pkParse = pk;
			} else {
				throw new RuntimeException("invalid pk type:" + pkType);
			}

			String delFlag = "";
			String delFlagType = "";
			Pattern p = Pattern.compile("del_flag|delete_flag", Pattern.CASE_INSENSITIVE);
			List<String> notShowAttrs = Arrays.asList("id", "createTime", "updateTime");
			List<IntrospectedColumn> columns = introspectedTable.getAllColumns();
			// 需要展示的属性列表
			List<Property> propertiesToShow = new ArrayList<>();
			// 需要特殊处理(如时间)
			StringBuilder dateParam = new StringBuilder("{");
			for (IntrospectedColumn column : columns) {

				String propName = JavaBeansUtil.getCamelCaseString(column.getActualColumnName(), false);
				
				Matcher m = p.matcher(column.getActualColumnName());
				boolean findDelflag = false;
				if (m.find()) {
					findDelflag = true;
					delFlag = propName;
					delFlagType = column.getFullyQualifiedJavaType().getShortName();
				}
				
				if (!notShowAttrs.contains(propName) && !findDelflag) {
					Property prop = new Property();
					prop.setName(propName);
					String remark = column.getRemarks();
					if (StringUtils.isBlank(remark)) {
						remark = propName;
					}
					prop.setRemark(remark);
					if ("TIMESTAMP".equals(column.getJdbcTypeName())) {
						prop.setDateType(true);
						dateParam.append(propName).append(":").append("'datetime',");
					}
					propertiesToShow.add(prop);
				}
				
			}
			if (',' == dateParam.charAt(dateParam.length()-1)) {
				dateParam.deleteCharAt(dateParam.length()-1);
			}
			dateParam.append("}");
			// System.out.println(delFlag);
			// System.out.println(delFlagType);
			

			Map<String, Object> root = new HashMap<String, Object>();
			root.put("props", properties);
			root.put("midnum", properties.size() / 2);
			root.put("modelName", modelName);
			root.put("modelRemark", modelRemark);
			root.put("propertiesToShow", propertiesToShow);
			root.put("operationColIndex", propertiesToShow.size() + colIndexOffset); // 列表展示时,最后一列操作列(编辑, 删除等)的序号
			root.put("modelVarName", StringUtils.uncapitalize(modelName));
			root.put("dateParam", dateParam);
			root.put("pk", pk);
			// root.put("modelConf", modelConf);
			// root.put("mapperConf", mapperConf);
			root.put("javaModelPackage", javaModelPackage);
			root.put("javaClientPackage", javaClientPackage);
			
			
			root.put("pkParse", pkParse);
			root.put("delFlag", delFlag);
			root.put("pkType", pkType);
			
			
			
			String srcJavaPath = this.prjPath + File.separator + "src\\main\\java";
			String webappPath = this.prjPath + File.separator + "src\\main\\webapp";
//			System.out.println(prjPath);
			TemplateProcessor tmplProcessor = new TemplateProcessor(srcJavaPath, webappPath, cfg, modelName, root);
			
			// 处理 service接口
			String serviceInterfaceTmplName = "IModelBiz.java.ftl";
			tmplProcessor.processTemplate(this.properties.getProperty("serviceInterfacePackage"), serviceInterfaceTmplName);
			
			// 处理 service实现
			String serviceImplTmplName = "ModelBizImpl.java.ftl";
			tmplProcessor.processTemplate(this.properties.getProperty("serviceImplPackage"), serviceImplTmplName);
			
			// 处理 controller
			String controllerTmplName = "ModelController.java.ftl";
			tmplProcessor.processTemplate(this.properties.getProperty("controllerPackage"), controllerTmplName);
			
			// 处理 jsp 列表展示页面
			String listPageTmplName = "/web/Model-list.jsp.ftl";
			tmplProcessor.processTemplate(this.properties.getProperty("webPagePath"), listPageTmplName, true, false);
			
			// 处理 jsp 增加页面
			String addPageTmplName = "/web/Model-add.jsp.ftl";
			tmplProcessor.processTemplate(this.properties.getProperty("webPagePath"), addPageTmplName, true, false);
			

		} catch (TemplateNotFoundException e) {
			e.printStackTrace();
		} catch (MalformedTemplateNameException e) {
			e.printStackTrace();
		} catch (ParseException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (TemplateException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	public static void main(String[] args) {
		
//		System.out.println(new File(BusinessPlugin.class.getResource("/").getFile()).exists());
	}

}
